home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / System / Infinity Windoid 2.5.1 / InfinityWindoid.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-16  |  33.8 KB  |  1,300 lines  |  [TEXT/MPS ]

  1. //******************************************************************************
  2. //
  3. //    FILE:
  4. //        InfinityWindoid.c
  5. //
  6. //    WRITTEN BY:
  7. //        Troy Gaul
  8. //        Infinity Systems
  9. //
  10. //        © 1991-94 Infinity Systems
  11. //        All rights reserved.
  12. //
  13. //    DESCRIPTION:
  14. //        This file contains the main source for a WDEF (Window Definition)
  15. //        resource. It provides a 'windoid' appearance use on floating windows. 
  16. //                
  17. //        See the file 'About Infinity Windoid' for more information and a list
  18. //        of features this WDEF supports.
  19. //
  20. //    HOW TO CONTACT THE AUTHOR:
  21. //        Send e-mail to: t-gaul@i-link.com
  22. //
  23. //------------------------------------------------------------------------------
  24.  
  25. //******************************************************************************
  26. //    Include files
  27. //------------------------------------------------------------------------------
  28.  
  29. #include "WindoidDefines.h"            // must be included before Apple interfaces
  30.  
  31. #include <Types.h>
  32. #include <Memory.h>
  33. #include <QuickDraw.h>
  34. #include <OSUtils.h>
  35. #include <Windows.h>
  36. #include <Palettes.h>
  37. #include <ToolUtils.h>
  38. #include <Desk.h>
  39. #include <Fonts.h>
  40.  
  41. #include "WindoidTypes.h"
  42. #include "WindoidUtil.h"
  43.  
  44. //******************************************************************************
  45. //    Function Prototypes    for main                             
  46. //------------------------------------------------------------------------------
  47.  
  48. void DoWInit(WindowPeek window, long param, short varCode);
  49. void DoWDispose(WindowPeek window, long param);
  50. long DoWHit(WindowPeek window, long param);
  51. void DoWDraw(WindowPeek window, long param);
  52. void DoWCalcRgns(WindowPeek window, long param);
  53. void DoWGrow(WindowPeek window, long param);
  54. void DoWDrawGIcon(WindowPeek window, long param);
  55.  
  56. //////**************************************************************************
  57. /////
  58. ////    Windoid Main Function                                                     
  59. ///
  60. //------------------------------------------------------------------------------
  61. //    This is the main entry point for all calls to this code resource. It
  62. //    dispatches to routines that correspond to the message it is given.
  63. //------------------------------------------------------------------------------
  64.  
  65. pascal long 
  66. main(short varCode, WindowPeek window, short message, long param) {
  67.     GrafPtr        savePort;
  68.     long        result;
  69.     Boolean        needSyncPorts;
  70.     
  71.     // This sets up the appropriate drawing environment, but only for those
  72.     // messages for which we actually need to draw.
  73.     needSyncPorts = (message == wDraw 
  74.                   || message == wHit 
  75.                   || message == wGrow
  76.                   || message == wDrawGIcon) && HasCQDraw();
  77.     if (needSyncPorts) {
  78.         GetPort(&savePort);
  79.         SyncPorts();
  80.     }
  81.     
  82.     switch (message) {
  83.         case wNew:            DoWInit(window, param, varCode);
  84.                             break;
  85.         
  86.         case wDispose:        DoWDispose(window, param);
  87.                             break;
  88.  
  89.         case wDraw:            DoWDraw(window, param & 0xFFFF);
  90.                             break;
  91.             // There's a tech note that says that for the draw message, only
  92.             // the low-order word of param is set correctly, so we should do
  93.             // this (AND with 0xFFFF) to be sure we're looking at the correct 
  94.             // value.
  95.             
  96.         case wHit:            result = DoWHit(window, param);        
  97.                             break;
  98.         
  99.         case wCalcRgns:        DoWCalcRgns(window, param);
  100.                             break;
  101.         
  102.         case wGrow:            DoWGrow(window, param);
  103.                             break;
  104.                             
  105.         case wDrawGIcon:    DoWDrawGIcon(window, param);
  106.                             break;
  107.     }
  108.     
  109.     if (needSyncPorts)
  110.         SetPort(savePort);
  111.     
  112.     return result;
  113. }
  114.  
  115. //////**************************************************************************
  116. /////
  117. ////    Routines to get Rects for title bar parts                                                     
  118. ///
  119. //------------------------------------------------------------------------------
  120.  
  121. static void 
  122. GetTitleBar(WindowPeek window, Rect *titleBar) {
  123.     *titleBar = (**(window->strucRgn)).rgnBBox;
  124.  
  125.     if (WindData.isHoriz) {                                        
  126.         // title bar on top
  127.         titleBar->bottom = titleBar->top + kTitleHeight;
  128.         titleBar->right -= 1;        // shadow compensation
  129.     } else {                                                            
  130.         // title bar on left
  131.         titleBar->right = titleBar->left + kTitleHeight;
  132.         titleBar->bottom -= 1;         // shadow compensation
  133.     }
  134. }
  135.  
  136. //------------------------------------------------------------------------------
  137.  
  138. static void 
  139. GetCloseBox(WindowPeek window, const Rect *titleRect, Rect *theRect) {
  140.     #pragma unused(window)
  141.  
  142.     *theRect = *titleRect;
  143.     if (WindData.isHoriz)
  144.         InsetRect(theRect, kGadgetMargin, kGadgetInset);    // titlebar on top
  145.     else
  146.         InsetRect(theRect, kGadgetInset, kGadgetMargin);    // titlebar on left
  147.  
  148.     theRect->bottom = theRect->top  + kGadgetSize;
  149.     theRect->right  = theRect->left + kGadgetSize;
  150. }
  151.  
  152. //------------------------------------------------------------------------------
  153. #ifdef ALLOW_ZOOM
  154.  
  155. static void 
  156. GetZoomBox(WindowPeek window, const Rect *titleRect, Rect *theRect) {
  157.     #pragma unused(window)
  158.  
  159.     *theRect = *titleRect;
  160.     if (WindData.isHoriz)
  161.         InsetRect(theRect, kGadgetMargin, kGadgetInset);    // titlebar on top
  162.     else
  163.         InsetRect(theRect, kGadgetInset, kGadgetMargin);    // titlebar on left
  164.  
  165.     theRect->top = theRect->bottom - kGadgetSize;
  166.     theRect->left = theRect->right - kGadgetSize;
  167. }
  168.  
  169. #endif
  170. //------------------------------------------------------------------------------
  171. #ifdef ALLOW_GROW
  172.  
  173. static void 
  174. GetGrowBox(WindowPeek window, Rect *theRect) {
  175.     GetGlobalContentRect(window, theRect);
  176.  
  177.     theRect->left = theRect->right++ - 15;
  178.     theRect->top = theRect->bottom++ - 15;
  179. }
  180.  
  181. #endif
  182.  
  183. //////**************************************************************************
  184. /////
  185. ////    Drawing routines                                                     
  186. ///
  187. //------------------------------------------------------------------------------
  188.  
  189. //******************************************************************************
  190. //    SetWFrameColor
  191. //------------------------------------------------------------------------------
  192.  
  193. static void
  194. SetWFrameColor(WindowPeek window, short variation) {
  195.     switch (variation) {
  196.         case blackandwhite:
  197.             ForeColor(blackColor);
  198.             break;
  199.  
  200. #ifndef SYS7_OR_LATER
  201.         case sys6color:
  202.             WctbForeColor(window, wFrameColor);
  203.             break;
  204. #endif
  205.  
  206.         case sys7color:
  207.             if (WindData.ignoreHilite || window->hilited)
  208.                 WctbForeColor(window, wFrameColor);
  209.             else
  210.                 AvgWctbForeColor(window, wHiliteColorLight, wHiliteColorDark,
  211.                                  wInactiveFramePct);
  212.             break;
  213.     }
  214. }
  215.  
  216. //******************************************************************************
  217. //    SetWTitleColor
  218. //------------------------------------------------------------------------------
  219. #ifdef TITLE_STRING
  220.  
  221. static void
  222. SetWTitleColor(WindowPeek window, short variation, Boolean active) {
  223.     switch (variation) {
  224.         case blackandwhite:
  225.             break;
  226.  
  227. #ifndef SYS7_OR_LATER
  228.         case sys6color:
  229.             WctbForeColor(window, wTextColor);
  230.             break;
  231. #endif
  232.             
  233.         case sys7color:
  234.             if (active)
  235.                 WctbForeColor(window, wTextColor);
  236.             else        // -- set the color for inactive titlebar text
  237.                 AvgWctbForeColor(window, wHiliteColorLight, wHiliteColorDark,
  238.                                  wInactiveTextPct);
  239.             break;
  240.     }
  241. }
  242.  
  243. #endif
  244.  
  245. //******************************************************************************
  246. //    SetWTitleBarColors
  247. //------------------------------------------------------------------------------
  248.  
  249. static void
  250. SetWTitleBarColors(WindowPeek window, short variation, Boolean active) {
  251.     // -- Set the foreground and background for the drawing of the 
  252.     //      titlebar pattern
  253.     switch (variation) {
  254.         case blackandwhite:
  255.             ColorsNormal();
  256.             break;
  257.             
  258. #ifndef SYS7_OR_LATER
  259.         case sys6color:
  260.             WctbForeColor(window, wHiliteColor);
  261.             WctbBackColor(window, wTitleBarColor);
  262.             break;
  263. #endif
  264.  
  265.         case sys7color:
  266.             if (active) {
  267.                 AvgWctbBackColor(window, wHiliteColorLight, wHiliteColorDark, 
  268.                                  wTitleBarLightPct);
  269.                 AvgWctbForeColor(window, wHiliteColorLight, wHiliteColorDark, 
  270.                                  wTitleBarDarkPct);
  271.             } else
  272.                 ColorsNormal();
  273.             break;
  274.     }
  275. }
  276.  
  277. //******************************************************************************
  278. //    SetWTitleBarColors
  279. //------------------------------------------------------------------------------
  280.  
  281. static void
  282. SetGadgetFrameEraseColors(WindowPeek window, short variation) {
  283.     // -- Set the foreground and background for the drawing of the 
  284.     //      titlebar pattern, in inverse so we can erase some of the
  285.     //      background by using normal drawing routines
  286.     switch (variation) {
  287.         case blackandwhite:
  288.             ForeColor(whiteColor);
  289.             BackColor(blackColor);
  290.             break;
  291.             
  292. #ifndef SYS7_OR_LATER
  293.         case sys6color:
  294.             WctbForeColor(window, wTitleBarColor);
  295.             WctbBackColor(window, wHiliteColor);
  296.             break;
  297. #endif
  298.  
  299.         case sys7color:
  300.             AvgWctbBackColor(window, wHiliteColorLight, wHiliteColorDark, 
  301.                              wTitleBarDarkPct);
  302.             AvgWctbForeColor(window, wHiliteColorLight, wHiliteColorDark, 
  303.                              wTitleBarLightPct);
  304.             break;
  305.     }
  306. }
  307.  
  308. //******************************************************************************
  309. //    DrawTitlebarTinges
  310. //------------------------------------------------------------------------------
  311.  
  312. static void
  313. DrawTitlebarTinges(WindowPeek window, short variation, const Rect *bounds) {
  314. #ifdef THICK_TITLEBAR
  315.     Rect tempRect = *bounds;
  316.     InsetRect(&tempRect, 1, 1);
  317.     
  318.     switch (variation) {
  319.         case blackandwhite:
  320.             ForeColor(whiteColor);
  321.             BackColor(blackColor);
  322.             FrameRect(&tempRect);
  323.             break;
  324.  
  325. #ifndef SYS7_OR_LATER
  326.         case sys6color:
  327.             WctbForeColor(window, wTitleBarColor);
  328.             FrameRect(&tempRect);
  329.             break;
  330. #endif
  331.             
  332.         case sys7color:
  333.             AvgWctbForeColor(window, wTingeLight, wTingeDark, 
  334.                              wTitleBarTingeDarkPct);
  335.             FrameBottomRightShading(tempRect);
  336.  
  337.             WctbForeColor(window, wTingeLight);
  338.             tempRect.right--;
  339.             tempRect.bottom--;
  340.             FrameTopLeftShading(tempRect);
  341.             break;
  342.     }
  343. #else
  344.     #pragma unused (window, variation, bounds)
  345. #endif
  346. }
  347.  
  348. //******************************************************************************
  349. //    DrawCloseBox
  350. //------------------------------------------------------------------------------
  351.  
  352. static void 
  353. DrawCloseBox(WindowPeek window, short variation, Rect *theRect) {
  354.     Rect tempRect;
  355.  
  356. #ifdef THICK_TITLEBAR
  357.     //
  358.     //    paint the area on the edges out with the background color
  359.     //
  360.     SetGadgetFrameEraseColors(window, variation);
  361.     InsetRect(theRect, -kTingeInset, -kTingeInset);
  362.     FrameRect(theRect);
  363.     InsetRect(theRect, kTingeInset, kTingeInset);
  364. #endif
  365.  
  366.     switch (variation) {
  367.         case blackandwhite:
  368.             ColorsNormal();
  369.             FrameBox(theRect);
  370.             break;
  371.         
  372. #ifndef SYS7_OR_LATER
  373.         case sys6color:
  374.             WctbForeColor(window, wHiliteColor);
  375.             WctbBackColor(window, wTitleBarColor);
  376.             FrameBox(theRect);
  377.             break;
  378. #endif
  379.         
  380.         case sys7color:
  381.             WctbForeColor(window, wTingeDark);
  382.             BackColor(whiteColor);
  383.             FrameTopLeftShading(*theRect);
  384.             
  385.             tempRect = *theRect;
  386.             tempRect.top++;
  387.             tempRect.left++;
  388.             WctbForeColor(window, wTingeLight);
  389.             FrameRect(&tempRect);
  390.  
  391.             InsetRect(&tempRect, 1, 1);
  392.             WctbForeColor(window, wTingeDark);
  393.             FrameBottomRightShading(tempRect);
  394.  
  395.             tempRect.right--;
  396.             tempRect.bottom--;
  397.             AvgWctbForeColor(window, wHiliteColorLight, wHiliteColorDark, 
  398.                              wCloseBoxColor);
  399.             PaintRect(&tempRect);
  400.             break;
  401.     }
  402. }
  403.  
  404. //******************************************************************************
  405. //    DrawZoomBox -- Draw zoom box
  406. //------------------------------------------------------------------------------
  407. #ifdef ALLOW_ZOOM
  408.  
  409. static void 
  410. DrawZoomBox(WindowPeek window, short variation, Rect *theRect) {
  411.     Rect tempRect;
  412.  
  413.     DrawCloseBox(window, variation, theRect);
  414.     tempRect = *theRect;
  415.     tempRect.bottom -= 3;
  416.     tempRect.right -= 3;
  417.  
  418.     switch (variation) {
  419.         case blackandwhite:
  420. #ifndef SYS7_OR_LATER
  421.         case sys6color:
  422. #endif
  423.             FrameRect(&tempRect);
  424.             break;
  425.         
  426.         case sys7color:
  427.             WctbForeColor(window, wTingeDark);
  428.             tempRect.left += 2;
  429.             tempRect.top += 2;
  430.             FrameBottomRightShading(tempRect);
  431.             break;
  432.     }
  433. }
  434.  
  435. #endif
  436. //******************************************************************************
  437. //    DrawXedBox -- Draw close or zoom box with an X in it (or inverted in B&W)
  438. //------------------------------------------------------------------------------
  439.  
  440. static void 
  441. DrawXedBox(WindowPeek window, short variation, Rect *theRect) {
  442.     switch (variation) {
  443.         case blackandwhite:
  444.             PaintRect(theRect);
  445.             break;
  446.             
  447. #ifndef SYS7_OR_LATER
  448.         case sys6color:
  449.             WctbForeColor(window, wHiliteColor);
  450.             PaintRect(theRect);
  451.             break;
  452. #endif
  453.             
  454.         case sys7color:
  455.             AvgWctbForeColor(window, wTingeLight, wTingeDark, wXedBoxPct);
  456.             PaintRect(theRect);
  457.             
  458.             WctbForeColor(window, wFrameColor);
  459.             FrameRect(theRect);
  460.             
  461.             MoveTo(theRect->left,      theRect->top       );    // Draw the 'X'
  462.             LineTo(theRect->right - 1, theRect->bottom - 1);
  463.             MoveTo(theRect->right - 1, theRect->top       );
  464.             LineTo(theRect->left,      theRect->bottom - 1);
  465.             break;
  466.     }
  467. }
  468.  
  469. //******************************************************************************
  470. //    DrawGrowBox
  471. //------------------------------------------------------------------------------
  472. #ifdef ALLOW_GROW
  473.  
  474. static void 
  475. DrawGrow3DBox(WindowPeek window, Rect *theRect, Boolean light) {
  476.     Rect tempRect = *theRect;
  477.     
  478.     WctbForeColor(window, wTingeDark);
  479.     FrameRect(theRect);
  480.     
  481.     // Add the top light outer border on the top-left edge
  482.     tempRect.left++;
  483.     tempRect.top++;
  484.     WctbForeColor(window, wTingeLight);
  485.     FrameTopLeftShading(tempRect);
  486.  
  487.     // Finally, fill in the center.
  488.     InsetRect(&tempRect, 1, 1);
  489.     AvgWctbForeColor(window, wHiliteColorLight, wHiliteColorDark, 
  490.                      light ? wGrowBoxColorLt : wGrowBoxColorDk);
  491.     PaintRect(&tempRect);
  492. }
  493.  
  494. //------------------------------------------------------------------------------
  495.  
  496. static void 
  497. DrawGrowBox(WindowPeek window, short variation, Rect *theRect) {
  498.     Rect tempRect; 
  499.     
  500.     if (!(WindData.ignoreHilite || window->hilited)) { 
  501. #ifndef SYS7_OR_LATER
  502.         if (variation == sys6color)
  503.             WctbForeColor(window, wFrameColor);
  504. #endif
  505.             
  506.         FrameBox(theRect);
  507.     } else
  508.         // Add the size box chevrons.
  509.         switch (variation) {
  510.             case blackandwhite:
  511. #ifndef SYS7_OR_LATER
  512.             case sys6color:
  513.                 if (variation == sys6color)
  514.                     WctbForeColor(window, wFrameColor);
  515.                 else
  516. #endif
  517.                     ColorsNormal();
  518.                 FrameBox(theRect);
  519.                 
  520.                 SetRect(&tempRect, theRect->right - 11, theRect->bottom - 11, 
  521.                                    theRect->right - 2, theRect->bottom - 2);
  522.                 FrameRect(&tempRect);
  523.                 
  524.                 SetRect(&tempRect, theRect->left + 3, theRect->top + 3,
  525.                                    theRect->left + 10, theRect->top + 10);
  526.                 FrameBox(&tempRect);
  527.                 break;
  528.             
  529.             case sys7color:
  530.                 WctbForeColor(window, wFrameColor);
  531.                 AvgWctbBackColor(window, wHiliteColorLight, wHiliteColorDark, 
  532.                                  wGrowBoxBackground);
  533.                 FrameBox(theRect);
  534.                 
  535.                 // -- Draw the dark border parts for the bottom rectangle
  536.                 SetRect(&tempRect, theRect->right - 12, theRect->bottom - 12, 
  537.                                    theRect->right - 3, theRect->bottom - 3);
  538.                 DrawGrow3DBox(window, &tempRect, false);
  539.                 
  540.                 // -- Draw the dark border parts for the top rectangle
  541.                 SetRect(&tempRect, theRect->left + 3, theRect->top + 3,
  542.                                    theRect->left + 9, theRect->top + 9);
  543.                 DrawGrow3DBox(window, &tempRect, true);
  544.                 break;
  545.         }
  546. }
  547.  
  548. #endif
  549. //------------------------------------------------------------------------------
  550.  
  551. static void
  552. GetTitlebarPat(Boolean active, Point *corner, Pattern *titlePat) {
  553.     // Choose correct pattern, depending on position of window in global
  554.     // coordinates. (Concept of new (2.3) version taken from _Macintosh 
  555.     // Programming Secrets_, Second Edition, by Scott Knaster and Keith 
  556.     // Rollin, page 423.)
  557.     long seed;
  558.  
  559.     if (active)
  560.         seed = 0x00550055;
  561.     else
  562.         seed = 0x00000000;
  563.  
  564. #ifdef THICK_TITLEBAR
  565.     if (IsOdd(corner->h))
  566.         seed <<= 1;
  567.     if (IsOdd(corner->v))
  568.         seed <<= 8;
  569. #else
  570.     if (IsEven(corner->h))
  571.         seed <<= 1;
  572.     if (IsEven(corner->v))
  573.         seed <<= 8;
  574. #endif
  575.  
  576.     *((long*) titlePat + 1) = *((long*) titlePat) = seed;
  577. }
  578.  
  579. //*****************************************************************************
  580. //    SubtractGadgetRect
  581. //-----------------------------------------------------------------------------
  582.  
  583. static void
  584. SubtractGadgetRect(RgnHandle theRgn, const Rect *theRect) {
  585.     Rect subRect = *theRect;
  586.     RgnHandle subRgn = NewRgn();
  587.     
  588. #ifdef THICK_TITLEBAR
  589.     InsetRect(&subRect, -kTingeInset, -kTingeInset);
  590.         // to give the correct visual appearance
  591. #endif
  592.     
  593.     RectRgn(subRgn, &subRect);
  594.     DiffRgn(theRgn, subRgn, theRgn);
  595.     
  596.     DisposeRgn(subRgn);
  597. }
  598.  
  599. //******************************************************************************
  600. //    DrawTitleString
  601. //------------------------------------------------------------------------------
  602.     // when this routine is called, the background color will be set to the
  603.     // color of the background of the titlebar
  604.  
  605. static void
  606. DrawTitleString(WindowPeek window, short variation, 
  607.                 const Rect *titleRect, Boolean active, 
  608.                 Rect *stringRect) {
  609. #ifdef TITLE_STRING
  610.     short maxWidth;
  611.     short titleWidth;
  612.     short inset;
  613.     short strAreaLeft;
  614.     Rect titleStrBounds;
  615.     RGBColor saveFore;
  616.     RgnHandle saveClip = NewRgn();
  617.     RgnHandle clipRgn = NewRgn();
  618.     
  619.     if (window->titleHandle != nil && (*window->titleHandle)[0] != 0
  620.         && WindData.isHoriz) {
  621.         maxWidth = titleRect->right - titleRect->left - 2 * kGadgetMargin;
  622.         strAreaLeft = titleRect->left + kGadgetMargin;
  623.         if (window->goAwayFlag || window->spareFlag) {
  624.             maxWidth -= 2 * (kGadgetSize + kGadgetMargin);
  625.             strAreaLeft += kGadgetSize + kGadgetMargin;
  626.         }
  627.         
  628.         if (maxWidth > 0) {
  629.             //
  630.             //    Set up fonts, colors for text drawing
  631.             //
  632.             TextFont(kTitleFont);
  633.             TextSize(kTitleSize);
  634.             TextFace(kTitleStyle);
  635.             TextMode(srcOr);
  636.             HLock((Handle) window->titleHandle);
  637.             
  638.             if (variation != blackandwhite)
  639.                 GetForeColor(&saveFore);
  640.             SetWTitleColor(window, variation, active);
  641.             
  642.             // -- calculate the width of the title string
  643.             titleWidth = StringWidth(*window->titleHandle)
  644.                          + 2 * kTitleMargin;
  645.             
  646.             // -- limit its size to maxWidth
  647.             titleWidth = (titleWidth > maxWidth) ? maxWidth : titleWidth;
  648.             
  649.             // -- determine where to position it
  650.             inset = (short) (maxWidth - titleWidth) / 2;
  651.  
  652.             //
  653.             //    The following is done to make the title appear centered
  654.             //
  655.             if (IsEven(titleWidth))                // We need an odd width or  
  656.                 titleWidth--;                    // the overlap is wrong
  657.  
  658. #ifndef THICK_TITLEBAR
  659.             inset -= IsOdd(inset);
  660.                 // This is done so that the title doesn't shift as the window's
  661.                 // width changes.
  662. #else
  663.             inset -= IsEven(inset);
  664. #endif
  665.                 
  666.             SetRect(&titleStrBounds, strAreaLeft + inset, 
  667.                                      titleRect->top + 1, 
  668.                                      strAreaLeft + inset + titleWidth, 
  669.                                      titleRect->bottom - 1); 
  670.  
  671. #ifdef THICK_TITLEBAR
  672.             // -- inset the bounds so as not to erase part of the tinges
  673.             if (active)
  674.                 InsetRect(&titleStrBounds, 0, kTingeInset);
  675. #endif        
  676.  
  677.             // -- make sure this area is cleared to the titlebar background color
  678.             EraseRect(&titleStrBounds);
  679.  
  680. #ifdef THICK_TITLEBAR
  681.             // -- outset it so decenders may overwrite the bottom tinge
  682.             if (active)
  683.                 InsetRect(&titleStrBounds, 0, -kTingeInset);
  684. #endif        
  685.  
  686.             // -- return the title string area's boundry
  687.             *stringRect = titleStrBounds;
  688.             
  689.             GetClip(saveClip);
  690.             
  691.             // -- get the region the title string should go into
  692.             InsetRect(&titleStrBounds, kTitleMargin, 0);
  693.             RectRgn(clipRgn, &titleStrBounds);
  694.             
  695.             // -- make sure we don't clobber other windows
  696.             SectRgn(saveClip, clipRgn, clipRgn);
  697.             SetClip(clipRgn);
  698.  
  699.             // -- draw the title
  700.             MoveTo(titleStrBounds.left, titleStrBounds.bottom - kTitleVDelta);
  701.             DrawString(*window->titleHandle);
  702.     
  703.             // -- clean up
  704.             SetClip(saveClip);
  705.  
  706.             if (variation != blackandwhite)
  707.                 RGBForeColor(&saveFore);
  708.  
  709.             HUnlock((Handle) window->titleHandle);
  710.             TextFont(systemFont);
  711.             TextSize(0);
  712.             TextFace(0);
  713.         }
  714.     }
  715.     DisposeRgn(saveClip);
  716.     DisposeRgn(clipRgn);
  717. #else
  718.     #pragma unused (window, variation, titleRect, active, stringRect)
  719. #endif
  720. }
  721.  
  722. //******************************************************************************
  723. //    DrawTitleBar -- Draw pattern/title into the title bar
  724. //------------------------------------------------------------------------------
  725.     // This routine actually draws the pattern into the titlebar. Note: it
  726.     // takes a Rect as a parameter (not by address) because it goes ahead and
  727.     // modifies it. I figured this was no worse than needing to copy it into
  728.     // a local variable, so I went ahead and did it this way.
  729.  
  730. static void 
  731. DrawTitleBar(WindowPeek window, short variation, const Rect *titleRect,
  732.              Boolean active) {
  733.     Rect        tempRect;
  734.     Rect        insetTitleRect;
  735.     Rect        stringRect;
  736.     Pattern        pat;
  737.     RgnHandle    titleRgn = NewRgn();
  738.     
  739.     SetRect(&stringRect, 0, 0, 0, 0);
  740.     
  741.     if (active)
  742.         DrawTitlebarTinges(window, variation, titleRect);
  743.     
  744.     SetWTitleBarColors(window, variation, active);
  745.     
  746.     //
  747.     //    Set up the starting region to be the whole titlebar, 
  748.     //    parts will then be 'punched out' of it.
  749.     //
  750.     insetTitleRect = *titleRect;
  751.     InsetRect(&insetTitleRect, 1, 1);
  752.     
  753.     if (active)
  754.         InsetRect(&insetTitleRect, kTingeInset, kTingeInset);
  755.     
  756.     RectRgn(titleRgn, &insetTitleRect);
  757.     
  758.     DrawTitleString(window, variation, titleRect, active, &stringRect);
  759.         // since the area affected by the title string is returned in
  760.         // stringRect, we can use it's left and right to draw the pattern
  761.     
  762.     if (!EmptyRect(&stringRect)) {
  763.         RgnHandle tempRgn = NewRgn();
  764.         
  765.         RectRgn(tempRgn, &stringRect);
  766.         DiffRgn(titleRgn, tempRgn, titleRgn);
  767.         
  768.         DisposeRgn(tempRgn);
  769.     }
  770.     
  771.     //
  772.     //    Subtract the Close Box
  773.     //
  774.     if (active && window->goAwayFlag) {
  775.         GetCloseBox(window, titleRect, &tempRect);
  776.         SubtractGadgetRect(titleRgn, &tempRect);
  777.     }
  778.  
  779. #ifdef ALLOW_ZOOM
  780.     //
  781.     //    Subtract the Zoom Box
  782.     //
  783.     if (active && window->spareFlag) {
  784.         GetZoomBox(window, titleRect, &tempRect);
  785.         SubtractGadgetRect(titleRgn, &tempRect);
  786.     }
  787. #endif
  788.     
  789.     GetTitlebarPat(active, (Point*) &titleRect->top, &pat);
  790.     FillRgn(titleRgn, (ConstPatternParam) &pat);
  791.  
  792.     DisposeRgn(titleRgn);
  793. }
  794.  
  795. //////**************************************************************************
  796. /////
  797. ////    Zoom handling                                                     
  798. ///
  799. //------------------------------------------------------------------------------
  800. #ifdef ALLOW_ZOOM
  801.     
  802. static void 
  803. SetZoomRects(WindowPeek window) {
  804.     Rect contRect;
  805.     
  806.     if (window->spareFlag) {
  807.         GetGlobalContentRect(window, &contRect);
  808.         WindData.wState.stdState = contRect;
  809. #ifdef MFI_ZOOM
  810.         if (WindData.isHoriz)                            // titlebar on top
  811.             contRect.bottom = contRect.top + 12;
  812.         else                                            // titlebar on left
  813.             contRect.right = contRect.left + 12;
  814. #endif
  815.         WindData.wState.userState = contRect;
  816.             // the stdState and user state might be backwards from how they
  817.             // would normally be used by an application. Check this for your
  818.             // own use and change them if necessary.
  819.     }
  820. }
  821.  
  822. //------------------------------------------------------------------------------
  823.  
  824. static long 
  825. GetZoomHitType(WindowPeek window) {
  826.     Rect contRect;
  827.     Rect stdRect;
  828.     
  829.     contRect = (**(window->contRgn)).rgnBBox;
  830.     stdRect = WindData.wState.stdState;
  831.     OffsetRect(&stdRect, -stdRect.left + contRect.left, 
  832.                          -stdRect.top + contRect.top);
  833.         // make topLeft the same for content and standard rects, and compare
  834.  
  835.     if (EqualRect(&contRect, &stdRect))
  836.         return wInZoomIn;        // go to user state (make small, MFI)
  837.     else
  838.         return wInZoomOut;        // go to standard state (make normal, MFI)
  839. }
  840.  
  841. #endif
  842. //////**************************************************************************
  843. /////
  844. ////    DoWInit -- Windoid initialization                                                     
  845. ///
  846. //------------------------------------------------------------------------------
  847.  
  848. void 
  849. DoWInit(WindowPeek window, long param, short varCode) {
  850.     #pragma unused(param)
  851.     Handle zoomDataHndl;
  852.     WindoidDataPtr wdata;
  853.  
  854.     window->spareFlag = false;
  855.     zoomDataHndl = NewHandle(sizeof(WindoidData));
  856.     if (zoomDataHndl) {
  857.         wdata = (WindoidDataPtr) *zoomDataHndl;        // make it easier to access
  858.         
  859.         wdata->closeToggle         = 0;
  860.         wdata->hasTitlebar        = true;
  861.         wdata->ignoreHilite        = false;
  862.  
  863. #ifdef ALLOW_GROW
  864.         wdata->hasGrow            = (varCode & noGrowDocProc) == 0;
  865. #endif
  866.  
  867. #ifdef ALLOW_VERT
  868.         wdata->isHoriz             = !((varCode & 1) || (varCode & 2));
  869. #else
  870.         wdata->isHoriz             = true;
  871. #endif
  872.  
  873. #ifdef ALWAYS_HILITE
  874.         wdata->ignoreHilite        = true;
  875. #endif
  876.  
  877. #ifdef MACAPP_STYLE
  878.         wdata->ignoreHilite        = !(kMacApp_toggleTBar & varCode);
  879. #endif
  880.  
  881. #ifdef THINK_STYLE
  882.         if ((varCode & 7) != 0 && (varCode & 7) != 2)
  883.             wdata->hasTitlebar    = false;
  884. #endif
  885.  
  886.         // -- set the window's data handle to the right value
  887.         window->dataHandle         = zoomDataHndl;
  888.  
  889. #ifdef ALLOW_ZOOM
  890.         wdata->zoomToggle        = 0;
  891.         window->spareFlag        = (zoomDocProc & varCode);
  892.         SetZoomRects(window);
  893. #endif
  894.  
  895.     }
  896. }
  897.  
  898. //////**************************************************************************
  899. /////
  900. ////    DoWDispose -- Windoid disposal                                                     
  901. ///
  902. //------------------------------------------------------------------------------
  903.  
  904. void 
  905. DoWDispose(WindowPeek window, long param) {
  906.     #pragma unused(param)
  907.  
  908.     if (window->dataHandle)
  909.         DisposeHandle(window->dataHandle);
  910. }
  911.  
  912. //////**************************************************************************
  913. /////
  914. ////    DoWHit -- Windoid hit routine                                                     
  915. ///
  916. //------------------------------------------------------------------------------
  917.  
  918. long 
  919. DoWHit(WindowPeek window, long param) {
  920.     Rect    titleRect;
  921.     Rect    theRect;
  922.     Point    hitPt;
  923.     long    result;
  924. #ifdef ALLOW_ZOOM
  925.     Rect    stdRect;
  926.     Rect    usrRect;
  927.     Rect    contentRect;
  928. #endif
  929.  
  930.     hitPt.v = HiWord(param);
  931.     hitPt.h = LoWord(param);
  932.     
  933.     result = wNoHit;
  934.     if (PtInRgn(hitPt, window->contRgn)) {
  935.         result = wInContent;
  936.  
  937. #ifdef ALLOW_GROW
  938.         // Look for a Grow region hit
  939.         if (WindData.hasGrow) {
  940.             GetGrowBox(window, &theRect);
  941.             InsetRect(&theRect, -1, -1);
  942.             if (PtInRect(hitPt, &theRect))
  943.                 result = wInGrow; 
  944.         }
  945. #endif
  946.  
  947.     } else {
  948.         GetTitleBar(window, &titleRect);
  949.         if (WindData.hasTitlebar && PtInRect(hitPt, &titleRect)) {
  950.             result = wInDrag;
  951.             if (WindData.ignoreHilite || window->hilited) {
  952.  
  953.                 if (window->goAwayFlag) {
  954.                     GetCloseBox(window, &titleRect, &theRect);
  955.                     if (PtInRect(hitPt, &theRect))
  956.                         result = wInGoAway;
  957.                 }
  958.  
  959. #ifdef ALLOW_ZOOM
  960.                 if (window->spareFlag) {
  961.                     GetZoomBox(window, &titleRect, &theRect);
  962.                     if (PtInRect(hitPt, &theRect)) {
  963.                         result = GetZoomHitType(window);
  964.  
  965.                         // Calculate Offset for Zoom Rects (make sure they
  966.                         // are up to date)
  967.                         contentRect = (**(window->contRgn)).rgnBBox;
  968.                         stdRect = WindData.wState.stdState;
  969.                         usrRect = WindData.wState.userState;
  970.                         
  971. #ifdef STAYPUT_ZOOM
  972.                         OffsetRect(&(WindData.wState.stdState), 
  973.                                    contentRect.left - stdRect.left,
  974.                                    contentRect.top  - stdRect.top);
  975.                         OffsetRect(&(WindData.wState.userState), 
  976.                                    contentRect.left - usrRect.left, 
  977.                                    contentRect.top  - usrRect.top);
  978. #else
  979.                         if (result == wInZoomIn) {
  980.                             OffsetRect(&(WindData.wState.stdState), 
  981.                                        contentRect.left - stdRect.left,
  982.                                        contentRect.top  - stdRect.top);
  983.                         } else {
  984.                             OffsetRect(&(WindData.wState.userState), 
  985.                                        contentRect.left - usrRect.left, 
  986.                                        contentRect.top  - usrRect.top);
  987.                         }
  988. #endif                        
  989.                     }
  990.                 }
  991. #endif
  992.             }
  993.         }
  994.     }
  995.     return result;
  996. }
  997.  
  998. //////**************************************************************************
  999. /////
  1000. ////    DoWDraw -- Windoid drawing routines                                                     
  1001. ///
  1002. //------------------------------------------------------------------------------
  1003.  
  1004. typedef struct {
  1005.     WindowPeek    wdlWindow;
  1006.     long        wdlParam;
  1007. } WDLDataRec;
  1008.     // This information is used to communicate with DeviceLoop callback routine
  1009.  
  1010. //******************************************************************************
  1011. //    Windoid drawing loop
  1012. //------------------------------------------------------------------------------
  1013.     // This routine actually does the real work of the drawing of stuff into
  1014.     // the window.
  1015.  
  1016. static pascal void 
  1017. WindoidDrawLoop(short depth, short deviceFlags, 
  1018.                 GDHandle targetDevice, WDLDataRec *userData) {
  1019.     WindowPeek window;
  1020.     Rect titleRect;
  1021.     Rect tempRect;
  1022.     short variation;
  1023.  
  1024.     window = userData->wdlWindow;    // make sure our macros work
  1025.     variation = CheckDisplay(depth, deviceFlags, targetDevice, window);
  1026.     
  1027.     switch (userData->wdlParam) {
  1028.         case wNoHit:
  1029.             BackColor(whiteColor);
  1030.             
  1031.             //
  1032.             //    Frame titlebar
  1033.             //
  1034.             if (WindData.hasTitlebar) {
  1035.                 GetTitleBar(window, &titleRect);
  1036.                 SetWFrameColor(window, variation);
  1037.                 FrameRect(&titleRect);
  1038.             }
  1039.             
  1040.             if (WindData.ignoreHilite || window->hilited) {
  1041.                 //
  1042.                 //    Draw titlebar interior
  1043.                 //
  1044.                 if (WindData.hasTitlebar)
  1045.                     DrawTitleBar(window, variation, &titleRect, true);
  1046.                 
  1047.                 //
  1048.                 //    Draw close box
  1049.                 //
  1050.                 if (window->goAwayFlag) {    
  1051.                     GetCloseBox(window, &titleRect, &tempRect);
  1052.                     DrawCloseBox(window, variation, &tempRect);
  1053.                 }
  1054.                     // Note: I have seen at least one windoid WDEF that is used
  1055.                     // by some applications that does not utilize this flag.
  1056.                     // In that case, I think it always had a close box (or it
  1057.                     // might even have used the varcode to determine this, but
  1058.                     // that wouldn't seem to be a good thing to do).
  1059.  
  1060. #ifdef ALLOW_ZOOM
  1061.                 //
  1062.                 //    Draw zoom box
  1063.                 //
  1064.                 if (window->spareFlag) {
  1065.                     GetZoomBox(window, &titleRect, &tempRect);
  1066.                     DrawZoomBox(window, variation, &tempRect);
  1067.                 }
  1068. #endif
  1069.             } else {
  1070.                 //
  1071.                 //    Draw dimmed titlebar
  1072.                 //
  1073.                 DrawTitleBar(window, variation, &titleRect, false);
  1074.             }
  1075.             
  1076.             //
  1077.             //    Draw content frame and shadow
  1078.             //
  1079.             tempRect = (**window->strucRgn).rgnBBox;
  1080.             tempRect.bottom--;
  1081.             tempRect.right--;
  1082.             
  1083.             SetWFrameColor(window, variation);
  1084.             FrameRect(&tempRect);
  1085.             
  1086.             //
  1087.             //    Draw Shadow
  1088.             //
  1089.             OffsetRect(&tempRect, 1, 1);
  1090.             if (variation == sys7color)
  1091.                 ForeColor(blackColor);        // in System 6, use the frame color
  1092.             FrameBottomRightShading(tempRect);
  1093.             break;
  1094.  
  1095.         //
  1096.         //    Toggle Go-Away Box
  1097.         //
  1098.         case wInGoAway:
  1099.             GetTitleBar(window, &titleRect);
  1100.             GetCloseBox(window, &titleRect, &tempRect);
  1101.             if (WindData.closeToggle)
  1102.                 DrawCloseBox(window, variation, &tempRect);
  1103.             else
  1104.                 DrawXedBox(window, variation, &tempRect);
  1105.             break;
  1106.         
  1107. #ifdef ALLOW_ZOOM
  1108.  
  1109.         //
  1110.         //    Toggle Zoom Box
  1111.         //
  1112.         default:
  1113.             if (window->spareFlag) {
  1114.                 GetTitleBar(window, &titleRect);
  1115.                 GetZoomBox(window, &titleRect, &tempRect);
  1116.                 if (WindData.zoomToggle)
  1117.                     DrawZoomBox(window, variation, &tempRect);
  1118.                 else
  1119.                     DrawXedBox(window, variation, &tempRect);
  1120.             }
  1121.             break;
  1122. #endif
  1123.     }
  1124.     ColorsNormal();
  1125. }
  1126.  
  1127. //------------------------------------------------------------------------------
  1128.  
  1129. void 
  1130. DoWDraw(WindowPeek window, long param) {
  1131.     WDLDataRec theUserData;
  1132.  
  1133.     if (window->visible) {
  1134.         theUserData.wdlWindow = window;
  1135.         theUserData.wdlParam = param;
  1136.         OurDeviceLoop(window->strucRgn, 
  1137.                       (DeviceLoopDrawingProcPtr) WindoidDrawLoop, 
  1138.                       (long) &theUserData, (DeviceLoopFlags) 0);
  1139.  
  1140.         switch (param) {
  1141.             case wNoHit:
  1142.                 // This is so param 0 doesn't get interpreted as a hit in the
  1143.                 // zoom box, incorrectly.
  1144.                 break;
  1145.                 
  1146.             case wInGoAway:                        // toggle go-away
  1147.                 WindData.closeToggle = ! WindData.closeToggle;
  1148.                 break;
  1149.             
  1150. #ifdef ALLOW_ZOOM
  1151.             default:                            // toggle zoom box
  1152.                 WindData.zoomToggle = ! WindData.zoomToggle;
  1153.                 break;
  1154. #endif
  1155.         }
  1156.     }
  1157. }
  1158.  
  1159. //////**************************************************************************
  1160. /////
  1161. ////    DoWCalcRgns -- Windoid region calculating routine                                                     
  1162. ///
  1163. //------------------------------------------------------------------------------
  1164.  
  1165. void 
  1166. DoWCalcRgns(WindowPeek window, long param) {
  1167.     #pragma unused(param)
  1168.     Rect theRect;
  1169.     RgnHandle tempRgn = NewRgn();
  1170.  
  1171.     // -- calculate the content Rect in global coordinates
  1172.     GetGlobalContentRect(window, &theRect);
  1173.     RectRgn(window->contRgn, &theRect);
  1174.  
  1175.     // -- start off with the structure equal to the content
  1176.     //    & make it include the window frame and titlebar
  1177.     InsetRect(&theRect, -1, -1);
  1178.     if (WindData.hasTitlebar) {
  1179.         if (WindData.isHoriz)
  1180.             theRect.top -= kTitleHeight - 1;
  1181.         else
  1182.             theRect.left -= kTitleHeight - 1;
  1183.     }
  1184.     RectRgn(window->strucRgn, &theRect);
  1185.     
  1186.     // -- add the shadow to the structure 
  1187.     OffsetRect(&theRect, 1, 1);
  1188.     RectRgn(tempRgn, &theRect);
  1189.     UnionRgn(tempRgn, window->strucRgn, window->strucRgn);
  1190.     
  1191.     DisposeRgn(tempRgn);
  1192. }
  1193.  
  1194. //////**************************************************************************
  1195. /////
  1196. ////    DoWGrow -- Draw the growing outline                                                     
  1197. ///
  1198. //------------------------------------------------------------------------------
  1199.  
  1200. void 
  1201. DoWGrow(WindowPeek window, long param) {
  1202. #ifdef ALLOW_GROW
  1203.     #pragma unused(window)
  1204.     Rect growingRect = *(Rect*) param;
  1205.     
  1206.     if (WindData.isHoriz)
  1207.         growingRect.top  -= kTitleHeight - 1;    // add room for the title bar
  1208.     else
  1209.         growingRect.left -= kTitleHeight - 1;    // add room for the title bar
  1210.     InsetRect(&growingRect, -1, -1);
  1211.     
  1212.     // Draw the window frame.
  1213.     FrameRect(&growingRect);
  1214.     
  1215.     if (WindData.isHoriz)
  1216.         growingRect.top  += kTitleHeight - 1;
  1217.     else
  1218.         growingRect.left += kTitleHeight - 1;
  1219.     
  1220.     // Now mark the title bar area
  1221.     MoveTo(growingRect.left, growingRect.top);
  1222.     if (WindData.isHoriz)
  1223.         LineTo(growingRect.right - 2, growingRect.top);
  1224.     else
  1225.         LineTo(growingRect.left, growingRect.bottom - 2);
  1226.     
  1227.     // Mark the scroll bars too
  1228.     MoveTo(growingRect.right - kScrollBarPixels, growingRect.top + 1);
  1229.     LineTo(growingRect.right - kScrollBarPixels, growingRect.bottom - 2);
  1230.     
  1231.     MoveTo(growingRect.left, growingRect.bottom - kScrollBarPixels);
  1232.     LineTo(growingRect.right - 2, growingRect.bottom - kScrollBarPixels);       
  1233. #else
  1234.     #pragma unused(window, param)
  1235. #endif
  1236. }
  1237.  
  1238. //////**************************************************************************
  1239. /////
  1240. ////    DoWDrawGIcon -- Draw the grow icon and scroll frame in the lower right                                                     
  1241. ///
  1242. //------------------------------------------------------------------------------
  1243. #ifdef ALLOW_GROW
  1244.  
  1245. static pascal void 
  1246. GrowBoxDrawLoop(short depth, short deviceFlags, 
  1247.                 GDHandle targetDevice, WDLDataRec *userData) {
  1248.     WindowPeek window;
  1249.     Rect theRect;
  1250.     short variation;
  1251.  
  1252.     window = userData->wdlWindow;    // make sure our macros work
  1253.     variation = CheckDisplay(depth, deviceFlags, targetDevice, window);
  1254.     
  1255.     GetGrowBox(window, &theRect);
  1256.     DrawGrowBox(window, variation, &theRect);
  1257.     
  1258.     ColorsNormal();
  1259. }
  1260.  
  1261. #endif
  1262. //------------------------------------------------------------------------------
  1263.  
  1264. void 
  1265. DoWDrawGIcon(WindowPeek window, long param) {
  1266. #ifdef ALLOW_GROW
  1267.     #pragma unused(param)
  1268.  
  1269.     if (window->visible && WindData.hasGrow) {
  1270.         WDLDataRec theUserData;
  1271.         RgnHandle saveClip = NewRgn();
  1272.         RgnHandle tempRgn = NewRgn();
  1273.         Point mappingPoint;
  1274.         
  1275.         SectRgn(window->port.visRgn, window->port.clipRgn, tempRgn);
  1276.  
  1277.         GetClip(saveClip);
  1278.         
  1279.         GetGlobalMappingPoint(window, &mappingPoint);
  1280.         OffsetRgn(tempRgn, mappingPoint.h, mappingPoint.v);
  1281.         
  1282.         SetClip(tempRgn);
  1283.         
  1284.         theUserData.wdlWindow = window;
  1285.         OurDeviceLoop(window->strucRgn, 
  1286.                       (DeviceLoopDrawingProcPtr) GrowBoxDrawLoop, 
  1287.                       (long) &theUserData, (DeviceLoopFlags) 0);
  1288.         
  1289.         SetClip(saveClip);
  1290.  
  1291.         DisposeRgn(saveClip);
  1292.         DisposeRgn(tempRgn);
  1293.     }
  1294. #else
  1295.     #pragma unused(window, param)
  1296. #endif
  1297. }
  1298.  
  1299. //******************************************************************************
  1300.